/**
 * Created by a on 2016/9/22.
 */
var express = require('express');
var router = express.Router();
var anarw=require('./anarw.js');
var math=require('mathjs');
var opt=require('./opt.json');
var cmn=require('../routes/comn.js');
var continuEvent=global.continuEvent;

function fail_create() {
    this.type=-1;
    this.startTime=new Date();
    this.outageDuration=1;
    this.notes="";
}
function accuracy_create() {
    this.X=[0];
    this.Y=[0];
}
function timeset(time) {
    var t=new Date(math.floor(time.time*1000+time.sec*1000));
    var ep=[t.getFullYear(),t.getMonth(),t.getDate(),0,0,0];
    return cmn.epoch2time(ep);
}
function acc95_create(time) {
    this.time=new timeset(time);
    this.mean=0;
    this.sigma=0;
    this.count=0;
}
function cont_create() {
    this.startTime=0;
    this.Horizontal=new accuracy_create();
    this.Vertical=new accuracy_create();
    this.Hori95={};
    this.Vert95={};
    this.contEvent={};
}
function acc_struct(Hori,Vert) {
    this.Hori=Hori;
    this.Vert=Vert;
}
function acc95_struct(Hori,Vert) {
    var i,j;
    var acc95={"Hori":{"X":[],"Y":[]},
    "Vert":{"X":[],"Y":[]}};
    for(i=0;i<Hori.length;i++){
        acc95.Hori.X.push(cmn.dayofyear(Hori[i].time));
        acc95.Hori.Y.push(Hori[i].mean+math.sqrt(Hori[i].sigma)*2);
    }
    for(i=0;i<Vert.length;i++){
        acc95.Vert.X.push(cmn.dayofyear(Vert[i].time));
        acc95.Vert.Y.push(Vert[i].mean+math.sqrt(Vert[i].sigma)*2);
    }
    return acc95;
}
function accuracyUpdate(X,Y,dd) {
    var i,j,h;
    for(i=0;i<X.length;i++){
        if(math.abs(X[i]-dd)<=opt.accu_val){
            Y[i]++;
            break;
        }
        if(X[i]-dd>opt.accu_val){
            if(i>0)
                h=X[i-1];
            else
                h=X[i];
            while(h<=dd){
                h+=opt.accu_val;
            }
            X.splice(i,0,h);
            Y.splice(i,0,1);
        }
    }
    if(i==X.length){
        h=X[X.length-1];
        while(h<=dd){
            h+=opt.accu_val;
        }
        X.push(h);
        Y.push(1);
    }
}
function accu95Update(sta_id,accH95,accV95,time,dH,dV) {
    if(accH95=={} || accV95=={}) {
        accH95 = acc95_create(time, dH);
        accV95 = acc95_create(time, dV);
    }else{
        if(cmn.timediff(time,accH95.time)>=24*3600){
            anarw.addacc95curr(sta_id,accH95,accV95);
            accH95 = acc95_create(time, dH);
            accV95 = acc95_create(time, dV);
            return;
        }
        accH95.mean=cmn.Average(dH,accH95.mean,accH95.count);
        accH95.sigma=cmn.vare(dH,accH95.sigma,accH95.count,accH95.mean);
        accH95.count++;
        accV95.mean=cmn.Average(dV,accV95.mean,accV95.count);
        accV95.sigma=cmn.vare(dV,accV95.sigma,accV95.count,accV95.mean);
        accV95.count++;
    }
}
function acc95_create(time,dd) {
    var acc95=new acc95_create(time);
    acc95.time=timeset(time);
    acc95.mean=dd;
    acc95.sigma=0;
    acc95.count++;
    return acc95;
}

router.post('/add',function (req,res) {
    try {
        var staid = req.body.sta_id;
        var posR = req.body.posR;
        if(posR.stat) {
            var dH = math.sqrt(posR.dX * posR.dX + posR.dY * posR.dY);
            var dV = posR.dZ;
            var df;
            var time = cmn.gpst2time(posR.week, posR.tow);
            if (!continuEvent.hasOwnProperty(staid)) {
                continuEvent[staid] = new cont_create();
                anarw.addaccevent(staid,continuEvent[staid]);
            }
            var cont = continuEvent[staid];
            if (posR.posNum < posR.navsys.length + 3) {
                var fail = new fail_create();
                fail.type = opt.svLack;
                fail.startTime = time;
                cont.contEvent=fail;
                anarw.addfail(cont);
            }
            if (dH >= opt.Herr) {
                var fail = new fail_create();
                fail.type = opt.Herr_exceed;
                fail.startTime = time;
                cont.contEvent=fail;
                anarw.addfail(cont);
            }
            if (posR.HPL >= opt.HAL) {
                var fail = new fail_create();
                fail.type = opt.HPL_exceed;
                fail.startTime = time;
                cont.contEvent=fail;
                anarw.addfail(cont);
            }
            accuracyUpdate(cont.Horizontal.X, cont.Horizontal.Y, dH);
            accuracyUpdate(cont.Vertical.X, cont.Vertical.Y, dV);
            accu95Update(staid,cont.Hori95,cont.Vert95, time, dH,dV);

            if (opt.isOutage && (df = cmn.timediff(time, cont.startTime)) > opt.accu_val) {
                var fail = new fail_create();
                fail.type = opt.trans_outage;
                fail.startTime = cont.startTime;
                fail.outageDuration = df;
                cont.contEvent=fail;
                anarw.addfail(cont);
            }
            cont.startTime = time;
        }
        res.send('ok');
    }catch(err){
        res.status(400).send(err.message);
    }
});
router.get('/get_acc',function (req,res) {
    var sta_id=req.query['sta_id'];
    //var sta_id=req.body.sta_id;
    if(!continuEvent.hasOwnProperty(sta_id)){
        res.status(400).send("no "+sta_id+" statistic data");
        return;
    }
    var acc=new acc_struct(continuEvent[sta_id].Horizontal,continuEvent[sta_id].Vertical);
    res.send(acc);
});
router.get('/get_acc95',function (req,res) {
    var sta_id=req.query['sta_id'];
    var time;
    if(!continuEvent.hasOwnProperty(sta_id)){
        res.status(400).send("no "+sta_id+" statistic data");
        return;
    }
    var cont = continuEvent[sta_id];
    var acc=acc95_struct(cont.Hori95,cont.Vert95);
    res.send(acc);
});
router.get('/get_integrity',function (req,res) {
    var sta_id=req.query['sta_id'];
    if(!continuEvent.hasOwnProperty(sta_id)){
        res.status(400).send("no "+sta_id+" statistic data");
        return;
    }
    res.send(continuEvent[sta_id].contEvent);
});
router.get('/get_continue',function (req,res) {
    var sta_id=req.query['sta_id'];
    var MTBF;
    if(!continuEvent.hasOwnProperty(sta_id)){
        res.status(400).send("no "+sta_id+" statistic data");
        return;
    }
    var cont = continuEvent[sta_id];
    MTBF=cmn.timediff(cont.currentTime,cont.startTime).time/3600;
    if(cont.contEvent.length==0)
        res.send(1);
    else
        res.send(1-1/(MTBF/cont.contEvent.length));
});
router.get('/get_available',function (req,res) {
    var sta_id=req.query['sta_id'];
    var MTBO,MTTR=0;
    if(!continuEvent.hasOwnProperty(sta_id)){
        res.status(400).send("no "+sta_id+" statistic data");
        return;
    }
    var cont = continuEvent[sta_id];
    MTBO=cmn.timediff(cont.currentTime,cont.startTime).time;
    for(var i=0;i<cont.contEvent.length;i++){
        MTTR+=cont.contEvent[i].outageDuration;
    }
    if(cont.contEvent.length==0)
        res.send(1);
    else
        res.send(MTBO/(MTBO+MTTR/(cont.contEvent.length)));
});



module.exports = router;